#include "River.h"
#include <SFML/Graphics.hpp>
#include <iostream>

using namespace sf;

int randint(int low, int high);

River::River(RiverSettings settings)
{
    this->position = settings.position;
    this->watermap = settings.watermap;
    this->normalizedHeightmap = settings.normalizedHeightmap;
    this->displayWatermap = settings.displayWatermap;
    this->riverCoordMod = settings.riverCoordMod;
    this->mapSize = settings.mapSize;
}


void River::flow()
{
    int x = position.x;
    int y = position.y;

    double heights[9];
    for (int hy = -1; hy <= 1; hy++)
    {
        for (int hx = -1; hx <= 1; hx++)
        {
            int heightIndex = (hx + 1) + (hy + 1) * 3;

            int mapX = (x + hx) * riverCoordMod;
            int mapY = (y + hy) * riverCoordMod;
            int heightMapIndex = mapX + mapY * mapSize;
            int waterMapIndex = (x + hx) + (y + hy) * (int)(mapSize / riverCoordMod);
            if (heightIndex != 4)
                heights[heightIndex] = watermap[waterMapIndex] > 0 ? 0 : normalizedHeightmap[heightMapIndex];
            else if (heightIndex == 4)
                heights[heightIndex] = normalizedHeightmap[heightMapIndex];
        }
    }
    //prevent rivers from crossing diagonally
    for (int sy = 1; sy <= 7; sy += 6)
    {
        for (int sx = 3; sx <= 5; sx += 2)
        {
            if (heights[sx] == 0 && heights[sy] == 0)
                heights[sy + (sx - 4)] = 0;
        }
    }

    int largestIndex = 0;
    for (int index = 0; index < 9; index++)
    {
        if (heights[index] >= heights[largestIndex])
        {
            largestIndex = index;
        }
    }
    int nextDirection = largestIndex;

    /*std::vector<int> higherIndices;
    for (int index = 0; index < 9; index++)
    {
        if (heights[index] > heights[4])
            higherIndices.push_back(index);
    }

    int nextDirection = 4;
    if (higherIndices.size() > 0)
    {
        int smallestIndex = 0;
        for (int index = 0; index < higherIndices.size(); index++)
        {
            if (heights[higherIndices.at(index)] < heights[higherIndices.at(smallestIndex)])
                smallestIndex = index;
            //std::cout << higherIndices.at(index) << ", ";
        }
        //std::cout << "size: " << higherIndices.size() << ", smallest: " << higherIndices.at(smallestIndex) << "\n";

        nextDirection = higherIndices.at(smallestIndex);
    }*/

    bool updateMaps = false;
    if (nextDirection != 4)
    {
        Vector2i newPosition = Vector2i(position.x + directions[nextDirection].x, position.y + directions[nextDirection].y);
        position = newPosition;
        addDirection((char)nextDirection);

        updateMaps = true;
    }
    else if (nextDirection == 4)
    {
        //std::cout << rivers.at(i).stepBack() << "\n";
        for (int steps = 0; steps < randint(4, 10); steps++)
        {
            int direction = 8 - stepBack();

            Vector2i newPosition = Vector2i(position.x + directions[direction].x, position.y + directions[direction].y);
            position = newPosition;
        }


        //rivers.at(i).addDirection((char)direction);

        /*std::cout << rivers.at(i).getPath()->size() << "<\n";
        for (int r = 0; r < rivers.at(i).getPath()->size(); r++)
        {
            std::cout << (int)rivers.at(i).getPath()->at(r);
        }
        std::cout << "\n";*/
    }

    if (updateMaps)
    {
        watermap[position.x + position.y * (mapSize / riverCoordMod)] = 1.0;

        displayWatermap[position.x * riverCoordMod + position.y * riverCoordMod * mapSize] = 1;

        /*int riverWidth = 5 - path.size();
        if (riverWidth <= 0)
            riverWidth = 1;
        std::cout << riverWidth << "\n";*/
        int riverWidth = 1;

        for (int t = 0; t < riverWidth; t++)
        {
            for (int j = 0; j <  riverCoordMod; j++)
            {
                int displayx = position.x * riverCoordMod - directions[nextDirection].x * j;
                int displayy = position.y * riverCoordMod - directions[nextDirection].y * j + t;
                displayWatermap[displayx + displayy * mapSize] = 1;
            }
        }
    }
}

int River::stepBack()
{
    if (path.size() > 2) // this value is not 0 to protect the first part of the river
    {
        int lastDirection = (int)(path.back());
        path.pop_back();
        return lastDirection;
    }
    else
    {
        return 4;
    }
}
